#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <string>
#include <sstream>
#include <sys/stat.h>
#include <fstream>
#include <iostream>


#define LOW 1
#define HIGH 5143
#define THRESHOLD 0.3

using namespace std;


bool fileExists(char *name)
{
	bool flag = false;
	fstream fin;
	fin.open(name,ios::in);
	if( fin.is_open() )
	{
		//cout<<"file exists"<<endl;
		flag=true;
	}
	fin.close();

	return flag;
}


int main( int argc, char** argv ) {
	
	IplImage* src;

	/** init distance table **/
	double *distances[4];

	for(int i = 0; i < 4; i++) {
		distances[i] = new double[HIGH-LOW+1];
		for(int  j = 0; j < HIGH-LOW+1; j++)
			distances[i][j] = -1;
	}
	

	/** initialize to bad distance */

	
	
    CvHistogram* hist[4];
	int binSize[4] = { 4, 8, 16, 32};
	
	for(int detail = 0; detail < 4; detail ++)
	{
      int    hist_size[] = { binSize[detail], binSize[detail] };
      float  h_ranges[]  = { 0, 180 };         
      float  s_ranges[]  = { 0, 255 };
      float* ranges[]    = { h_ranges, s_ranges };
      hist[detail] = cvCreateHist( 2, hist_size, CV_HIST_ARRAY,ranges, 1);
    }

	/** read target image and calculate histogram * 4 **/
	if( argc == 2 && (src=cvLoadImage(argv[1], 1))!= 0) {
        /** Initialize: Compute the HSV image and decompose it into separate planes. **/
        IplImage* hsv = cvCreateImage( cvGetSize(src), 8, 3 ); 
        cvCvtColor( src, hsv, CV_BGR2HSV ); 
        IplImage* h_plane  = cvCreateImage( cvGetSize(src), 8, 1 );
        IplImage* s_plane  = cvCreateImage( cvGetSize(src), 8, 1 );
        IplImage* v_plane  = cvCreateImage( cvGetSize(src), 8, 1 );
        IplImage* planes[] = { h_plane, s_plane };
        cvCvtPixToPlane( hsv, h_plane, s_plane, v_plane, 0 );//src,dst1,dst2,dst3
		
		/** build and compute histogram **/    
		for(int i = 0; i < 4; i++)
		{
			cvCalcHist( planes, hist[i], 0, 0 );
			cvNormalizeHist( hist[i], 1.0 );  
		}

		cvNamedWindow( "Source", 1 );
        cvShowImage(   "Source", src );
	}
	else {
		printf("input file unreadable\n");
		return 0;
	}


	/** compare lowest detail with all available histograms **/
	/** try all images **/
	int detail = 0;
	string s000("000"), s00("00"), s0("0");

    for(int i = LOW; i <= HIGH; i++)
	{
		stringstream ss;
		ss << i;
		string is = ss.str();
		string num = i < 10 ? (s000 + is) : ( i < 100 ? ( s00 + is) : (i<1000 ? s0 + is : is));
		
		stringstream sbin;
		sbin << binSize[detail];
		string outfilename(string("hist")+num+string("_")+string(sbin.str()));

		CvHistogram *targethist, *result;
		
		/*{
		  int    hist_size[] = { binSize[detail], binSize[detail] };
		  float  h_ranges[]  = { 0, 180 };         
		  float  s_ranges[]  = { 0, 255 };
		  float* ranges[]    = { h_ranges, s_ranges };
		  targethist = cvCreateHist( 2, hist_size, CV_HIST_ARRAY,ranges, 1);
		}*/

		if(fileExists((char*)outfilename.c_str()))
		if((targethist = (CvHistogram*) cvLoad((char*)outfilename.c_str()))!=NULL)
		{		
			cvNormalizeHist( targethist, 1.0 );
			distances[0][i-LOW] = cvCompareHist(hist[0], targethist, CV_COMP_BHATTACHARYYA);
			//printf("	d:%f\n",distances[detail][i-LOW]);
		}
		//if(targethist!=NULL)
		//	cvReleaseHist(&targethist);
	}
	
	/** go deeper **/
	int out = 0;
	for(detail = 1; detail < 4; detail++)
	{
		//printf("detail:%d\n",detail);
		for(int i = LOW; i <= HIGH; i++)
		{
			if(distances[detail-1][i-LOW] == -1 || distances[detail-1][i-LOW] >= THRESHOLD) {
				//printf("out:%d\n",out++);
				continue;
			}

			stringstream ss;
			ss << i;
			string is = ss.str();
			string num = i < 10 ? (s000 + is) : ( i < 100 ? ( s00 + is) : (i<1000 ? s0 + is : is));
			
			stringstream sbin;
			sbin << binSize[detail];
			string outfilename(string("hist")+num+string("_")+string(sbin.str()));

			CvHistogram *targethist, *result;
			
			/*{
			  int    hist_size[] = { binSize[detail], binSize[detail] };
			  float  h_ranges[]  = { 0, 180 };         
			  float  s_ranges[]  = { 0, 255 };
			  float* ranges[]    = { h_ranges, s_ranges };
			  targethist = cvCreateHist( 2, hist_size, CV_HIST_ARRAY,ranges, 1);
			}		*/	

	   		/** visualize histogram **/
			/*if(i==1)
			{
				int scale = 10;
				IplImage* hist_img = cvCreateImage( cvSize( binSize[detail] * scale, binSize[detail] * scale ), 8, 3 );
				cvZero( hist_img );
			    
				float max_value = 0;
				cvGetMinMaxHistValue( hist[detail], 0, &max_value, 0, 0 );

				for( int h = 0; h < binSize[detail]; h++ ) {
					for( int s = 0; s < binSize[detail]; s++ ) {
						float bin_val = cvQueryHistValue_2D( hist[detail], h, s );
						int intensity = cvRound( bin_val * 255 / max_value );
						cvRectangle( hist_img, cvPoint( h*scale, s*scale ), cvPoint( (h+1)*scale - 1, (s+1)*scale - 1), CV_RGB(intensity,intensity,intensity), CV_FILLED );
					}
				}

				cvNamedWindow( "H-S Histogram-src", 1 );
				cvShowImage(   "H-S Histogram-src", hist_img );
			}*/
			

			if(fileExists((char*)outfilename.c_str()))
			if((targethist = (CvHistogram*) cvLoad((char*)outfilename.c_str()))!=NULL)
			{	
				cvNormalizeHist(targethist, 1.0 );
				distances[detail][i-LOW] = cvCompareHist(hist[detail], targethist, CV_COMP_BHATTACHARYYA);	
				//printf("	d:%f\n",distances[detail][i-LOW]);
			}
		/*	if(targethist!=NULL)
				cvReleaseHist(&targethist);*/
		}
		
	}
	
	
	int cnt = 0;
	for(int i = LOW; i <= HIGH; i++)
	{
		if(distances[detail-1][i-LOW] == -1 || distances[3][i-LOW] >= THRESHOLD)
		{
			//printf("out:%d\n",out++);
			continue;
		}

		if(cnt < 10)
		{

			stringstream ss;
			ss << i;
			string is = ss.str();
			string num = i < 10 ? (s000 + is) : ( i < 100 ? ( s00 + is) : (i<1000 ? s0 + is : is));
			string filename = "../../preprocess/preprocess/tempimg/img" + num + ".jpg";	

			IplImage *src=cvLoadImage((char*)filename.c_str(), 1);
			cvNamedWindow( (char*)filename.c_str(), 1 );
			cvShowImage( (char*)filename.c_str(), src );
			cnt++;
		}

		printf("%d:%f\n",i, distances[3][i-LOW]);
		
	}

	


    //cvNamedWindow( "H-S Histogram", 1 );
    //cvShowImage(   "H-S Histogram", hist_img );
    cvWaitKey(0);
	
    
}


//if(i==1)
//				{
//					int scale = 10;
//					IplImage* hist_img = cvCreateImage( cvSize( binSize[detail] * scale, binSize[detail] * scale ), 8, 3 );
//					cvZero( hist_img );
//				    
//					float max_value = 0;
//					cvGetMinMaxHistValue( targethist, 0, &max_value, 0, 0 );
//
//					for( int h = 0; h < binSize[detail]; h++ ) {
//						for( int s = 0; s < binSize[detail]; s++ ) {
//							float bin_val = cvQueryHistValue_2D(  targethist, h, s );
//							int intensity = cvRound( bin_val * 255 / max_value );
//							cvRectangle( hist_img, cvPoint( h*scale, s*scale ), cvPoint( (h+1)*scale - 1, (s+1)*scale - 1), CV_RGB(intensity,intensity,intensity), CV_FILLED );
//						}
//					}
//
//					cvNamedWindow( "H-S Histogram-tar", 1 );
//					cvShowImage(   "H-S Histogram-tar", hist_img );
//				}